package rad.framework.mda.properties.views;

import java.util.ArrayList;
import java.util.Iterator;
import java.util.List;

import rad.framework.uml2.uml.edit.providers.ElementItemProvider;

import org.eclipse.emf.edit.provider.IItemPropertyDescriptor;
import org.eclipse.emf.edit.provider.IItemPropertySource;
import org.eclipse.emf.edit.ui.provider.PropertyDescriptor;
import org.eclipse.emf.edit.ui.provider.PropertySource;
import org.eclipse.jface.viewers.CellEditor;
import org.eclipse.jface.viewers.DialogCellEditor;
import org.eclipse.jface.viewers.ILabelProvider;
import org.eclipse.jface.viewers.LabelProvider;
import org.eclipse.swt.graphics.Image;
import org.eclipse.swt.widgets.Composite;
import org.eclipse.swt.widgets.Control;
import org.eclipse.swt.widgets.Label;
import org.eclipse.ui.views.properties.IPropertyDescriptor;
import org.eclipse.ui.views.properties.IPropertySource;
import org.eclipse.uml2.common.edit.provider.IItemQualifiedTextProvider;
import org.eclipse.uml2.uml.UMLPackage;

/**
 * @author boudyacho
 * 
 */
public class UML2PropertySource extends PropertySource implements
		IPropertySource {

	protected List stereotypeApplicationItemPropertyDescriptors = null;

	/**
	 * @param object
	 * @param itemPropertySource
	 */
	public UML2PropertySource(Object object,IItemPropertySource itemPropertySource) {
		super(object, itemPropertySource);
	}

	/* (non-Javadoc)
	 * @see org.eclipse.emf.edit.ui.provider.PropertySource#createPropertyDescriptor(org.eclipse.emf.edit.provider.IItemPropertyDescriptor)
	 */
	protected IPropertyDescriptor createPropertyDescriptor(IItemPropertyDescriptor itemPropertyDescriptor) {
		return new UML2PropertyDescriptor(object, itemPropertyDescriptor);
	}

	/* (non-Javadoc)
	 * @see org.eclipse.emf.edit.ui.provider.PropertySource#getPropertyDescriptors()
	 */
	public IPropertyDescriptor[] getPropertyDescriptors() {
		List propertyDescriptors = new ArrayList();

		List itemPropertyDescriptors = itemPropertySource.getPropertyDescriptors(object);

		if (itemPropertyDescriptors != null) {

			for (Iterator i = itemPropertyDescriptors.iterator(); i.hasNext();) {
				propertyDescriptors.add(createPropertyDescriptor((IItemPropertyDescriptor) i.next()));
			}
		}

		if (itemPropertySource instanceof ElementItemProvider) {
			stereotypeApplicationItemPropertyDescriptors = ((ElementItemProvider) itemPropertySource)
					.getStereotypeApplicationPropertyDescriptors(object);

			if (stereotypeApplicationItemPropertyDescriptors != null) {

				for (Iterator i = stereotypeApplicationItemPropertyDescriptors.iterator(); i.hasNext();) {
					propertyDescriptors.add(createPropertyDescriptor((IItemPropertyDescriptor) i.next()));
				}
			}
		}

		return (IPropertyDescriptor[]) propertyDescriptors.toArray(new IPropertyDescriptor[propertyDescriptors.size()]);
	}

	/**
	 * @param propertyId
	 * @return
	 */
	protected IItemPropertyDescriptor getItemPropertyDescriptor(Object propertyId) {
		IItemPropertyDescriptor itemPropertyDescriptor = itemPropertySource.getPropertyDescriptor(object, propertyId);
		return itemPropertyDescriptor == null && itemPropertySource instanceof ElementItemProvider ? ((ElementItemProvider) itemPropertySource).getStereotypeApplicationPropertyDescriptor(object, propertyId): itemPropertyDescriptor;
	}

	/* (non-Javadoc)
	 * @see org.eclipse.emf.edit.ui.provider.PropertySource#getPropertyValue(java.lang.Object)
	 */
	public Object getPropertyValue(Object propertyId) {
		return getItemPropertyDescriptor(propertyId).getPropertyValue(object);
	}

	/* (non-Javadoc)
	 * @see org.eclipse.emf.edit.ui.provider.PropertySource#isPropertySet(java.lang.Object)
	 */
	public boolean isPropertySet(Object propertyId) {
		return getItemPropertyDescriptor(propertyId).isPropertySet(object);
	}

	/* (non-Javadoc)
	 * @see org.eclipse.emf.edit.ui.provider.PropertySource#resetPropertyValue(java.lang.Object)
	 */
	public void resetPropertyValue(Object propertyId) {
		getItemPropertyDescriptor(propertyId).resetPropertyValue(object);
	}

	/* (non-Javadoc)
	 * @see org.eclipse.emf.edit.ui.provider.PropertySource#setPropertyValue(java.lang.Object, java.lang.Object)
	 */
	public void setPropertyValue(Object propertyId, Object value) {
		getItemPropertyDescriptor(propertyId).setPropertyValue(object, value);
	}

	/**
	 * @author boudyacho
	 *
	 */
	protected static class UML2PropertyDescriptor extends PropertyDescriptor {

		protected UML2PropertyDescriptor(Object object,IItemPropertyDescriptor itemPropertyDescriptor) {
			super(object, itemPropertyDescriptor);
		}

		protected ILabelProvider getEditLabelProvider() {

			final ILabelProvider editLabelProvider = super.getEditLabelProvider();
			return new LabelProvider() {
				public String getText(Object object) {
					return itemPropertyDescriptor instanceof IItemQualifiedTextProvider ? ((IItemQualifiedTextProvider) itemPropertyDescriptor).getQualifiedText(object): editLabelProvider.getText(object);
				}

				public Image getImage(Object object) {
					return editLabelProvider.getImage(object);
				}
			};
		}

		/* (non-Javadoc)
		 * @see org.eclipse.emf.edit.ui.provider.PropertyDescriptor#createPropertyEditor(org.eclipse.swt.widgets.Composite)
		 */
		public CellEditor createPropertyEditor(Composite composite) {
			Object feature = itemPropertyDescriptor.getFeature(object);
			if (feature.equals(UMLPackage.eINSTANCE.getTypedElement_Type())) {
				CellEditor editor = new DialogCellEditor(composite) {
					@SuppressWarnings("unchecked")
					protected Object openDialogBox(Control cellEditorWindow) {
						TypeListSelectionDialog dialog = new TypeListSelectionDialog(cellEditorWindow.getShell(), new ArrayList(itemPropertyDescriptor.getChoiceOfValues(object)),getEditLabelProvider());
						dialog.open();
						Object[] results = dialog.getResult();
						return results != null ? results[0] : null;
					}

					protected void updateContents(Object value) {
						Label label = getDefaultLabel();
						if (label == null)
							return;
						String text = "";
						if (value != null)
							text = getLabelProvider().getText(value);
						label.setText(text);
					}
				};
				return editor;
			}
			feature = itemPropertyDescriptor.getFeature(object);
			if (feature.equals(UMLPackage.eINSTANCE.getCallOperationAction_Operation())) {
				CellEditor editor = new DialogCellEditor(composite) {
					@SuppressWarnings("unchecked")
					protected Object openDialogBox(Control cellEditorWindow) {
						OperationListSelectionDialog dialog = new OperationListSelectionDialog(cellEditorWindow.getShell(), new ArrayList(itemPropertyDescriptor.getChoiceOfValues(object)),getEditLabelProvider());
						dialog.open();
						Object[] results = dialog.getResult();
						return results != null ? results[0] : null;
					}

					protected void updateContents(Object value) {
						Label label = getDefaultLabel();
						if (label == null)
							return;
						String text = "";
						if (value != null)
							text = getLabelProvider().getText(value);
						label.setText(text);
					}
				};
				return editor;
			}
			return super.createPropertyEditor(composite);
		}
	}
}
